/*
 *    This file is part of SSHTunneler.
 *
 *    Copyright 2009 Jean-Sebastien Gelinas <calestar@gmail.com>
 *
 *    SSHTunneler is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    SSHTunneler is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with SSHTunneler.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package sshtunneler.client.gui;

import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.jdom.JDOMException;

import sshtunneler.client.SSHTunnelerApp;
import sshtunneler.client.data.Config;
import sshtunneler.client.data.TunnelerServer;
import sshtunneler.client.data.TunnelerServerContainer;
import sshtunneler.client.data.TunnelerServerTunnelFile;
import sshtunneler.client.ssh.SSHConnectionContainer;
import sshtunneler.library.Server;
import sshtunneler.library.ServerTunnelFile;
import sshtunneler.server_tunnel.tree.MyServerTunnelTreeNode;
import sshtunneler.toolsgui.ToolConfig;

public class SSHTunnelerView extends JFrame implements MouseListener {
	private static final long serialVersionUID = 6690170738408542298L;
	private ServerTunnelTree st_tree;

	public SSHTunnelerView() {
		this.initComponents();

		this.initTree();
	}

	public void initTree() {
		this.jTree1.setCellRenderer(new ServerTunnelCellRenderer());
		this.jTree1.addMouseListener(this);
		this.jTree1.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);

		this.st_tree.getRoot().refresh();
	}

	public void refresh_tree() {
		this.st_tree.getRoot().refresh();
	}

	private void initComponents() {
		this.st_tree = new ServerTunnelTree();
		this.mainPanel = new javax.swing.JPanel();
		this.jScrollPane1 = new javax.swing.JScrollPane();
		this.jTree1 = new javax.swing.JTree(this.st_tree.getRoot());
		this.menuBar = new javax.swing.JMenuBar();
		javax.swing.JMenu fileMenu = new javax.swing.JMenu();
		this.jSeparator3 = new javax.swing.JSeparator();
		this.menu_item_load_srv_tunnel = new javax.swing.JMenuItem();
		this.menu_item_save_srv_tunnel = new javax.swing.JMenuItem();
		this.jSeparator1 = new javax.swing.JSeparator();
		javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
		this.jMenu1 = new javax.swing.JMenu();
		this.mnu_show_config = new javax.swing.JMenuItem();
		this.mnu_tools = new javax.swing.JMenuItem();
		this.jSeparator2 = new javax.swing.JSeparator();
		this.mnu_load_config = new javax.swing.JMenuItem();
		this.mnu_save_config = new javax.swing.JMenuItem();
		javax.swing.JMenu helpMenu = new javax.swing.JMenu();
		javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();

		this.setMinimumSize(new java.awt.Dimension(300, 300));

		this.mainPanel.setName("mainPanel");
		this.mainPanel.setLayout(new java.awt.BorderLayout());

		this.jScrollPane1.setName("jScrollPane1");

		this.jTree1.setName("Servers");
		this.jTree1
				.addTreeWillExpandListener(new javax.swing.event.TreeWillExpandListener() {
					public void treeWillCollapse(
							javax.swing.event.TreeExpansionEvent evt)
							throws javax.swing.tree.ExpandVetoException {
					}

					public void treeWillExpand(
							javax.swing.event.TreeExpansionEvent evt)
							throws javax.swing.tree.ExpandVetoException {
						SSHTunnelerView.this.jTree1TreeWillExpand(evt);
					}
				});
		this.jScrollPane1.setViewportView(this.jTree1);

		this.mainPanel.add(this.jScrollPane1, java.awt.BorderLayout.CENTER);

		this.getContentPane().add(this.mainPanel, java.awt.BorderLayout.CENTER);

		this.menuBar.setName("menuBar");

		fileMenu.setText("File");
		fileMenu.setName("fileMenu");

		this.jSeparator3.setName("jSeparator3");
		fileMenu.add(this.jSeparator3);

		this.menu_item_load_srv_tunnel.setText("Load server/tunnel config");
		this.menu_item_load_srv_tunnel.setName("menu_item_load_srv_tunnel");
		this.menu_item_load_srv_tunnel
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						SSHTunnelerView.this
								.menu_item_load_srv_tunnelActionPerformed(evt);
					}
				});
		fileMenu.add(this.menu_item_load_srv_tunnel);

		this.menu_item_save_srv_tunnel.setText("Save server/tunnel config");
		this.menu_item_save_srv_tunnel.setName("menu_item_save_srv_tunnel");
		this.menu_item_save_srv_tunnel
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						SSHTunnelerView.this
								.menu_item_save_srv_tunnelActionPerformed(evt);
					}
				});
		fileMenu.add(this.menu_item_save_srv_tunnel);

		this.jSeparator1.setName("jSeparator1");
		fileMenu.add(this.jSeparator1);

		exitMenuItem.setText("Quit");
		exitMenuItem.setName("exitMenuItem");
		exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				SSHTunnelerView.this.exitMenuItemActionPerformed(evt);
			}
		});
		fileMenu.add(exitMenuItem);

		this.menuBar.add(fileMenu);

		this.jMenu1.setText("Config");
		this.jMenu1.setName("jMenu1");

		this.mnu_show_config.setText("Show config");
		this.mnu_show_config.setName("mnu_show_config");
		this.mnu_show_config
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						SSHTunnelerView.this
								.mnu_show_configActionPerformed(evt);
					}
				});
		this.jMenu1.add(this.mnu_show_config);

		this.mnu_tools.setText("Show tools config");
		this.mnu_tools.setName("mnu_tools");
		this.mnu_tools.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				SSHTunnelerView.this.mnu_toolsActionPerformed(evt);
			}
		});
		this.jMenu1.add(this.mnu_tools);

		this.jSeparator2.setName("jSeparator2");
		this.jMenu1.add(this.jSeparator2);

		this.mnu_load_config.setText("Load config");
		this.mnu_load_config.setName("mnu_load_config");
		this.mnu_load_config
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						SSHTunnelerView.this
								.mnu_load_configActionPerformed(evt);
					}
				});
		this.jMenu1.add(this.mnu_load_config);

		this.mnu_save_config.setText("Save config");
		this.mnu_save_config.setName("mnu_save_config");
		this.mnu_save_config
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						SSHTunnelerView.this
								.mnu_save_configActionPerformed(evt);
					}
				});
		this.jMenu1.add(this.mnu_save_config);

		this.menuBar.add(this.jMenu1);

		helpMenu.setText("Help");
		helpMenu.setName("helpMenu");

		aboutMenuItem.setText("About");
		aboutMenuItem.setName("aboutMenuItem");
		aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				SSHTunnelerView.this.aboutMenuItemActionPerformed(evt);
			}
		});
		helpMenu.add(aboutMenuItem);

		this.menuBar.add(helpMenu);

		this.setJMenuBar(this.menuBar);
	}

	private void jTree1TreeWillExpand(javax.swing.event.TreeExpansionEvent evt)
			throws javax.swing.tree.ExpandVetoException {
		TreePath selPath = evt.getPath();
		Object selection = selPath.getLastPathComponent();

		if (selection == null || !(selection instanceof MyServerTunnelTreeNode)) {
			return;
		}
		this.refreshNode((MyServerTunnelTreeNode) selection);
	}

	private void menu_item_load_srv_tunnelActionPerformed(
			java.awt.event.ActionEvent evt) {
		boolean found_connected_server = false;

		for (Server server : TunnelerServerContainer.inst.getServers()) {
			if (SSHConnectionContainer.inst.hasConnectionTo(server)) {
				found_connected_server = true;
				break;
			}
		}

		if (found_connected_server) {
			int res = JOptionPane
					.showConfirmDialog(
							null,
							"Some connections are active, loading a config file will reset all connections. Continue ?",
							"Active connections detected",
							JOptionPane.YES_NO_OPTION);

			if (res == JOptionPane.NO_OPTION) {
				return;
			}
			for (Server server : TunnelerServerContainer.inst.getServers()) {
				if (SSHConnectionContainer.inst.hasConnectionTo(server)) {
					SSHConnectionContainer.inst.closeConnectionTo(server);
				}
			}
		}

		JFileChooser chooser = new JFileChooser();
		chooser.setMultiSelectionEnabled(false);
		chooser.setFileFilter(ServerTunnelFile.filter);

		chooser.showOpenDialog(null);

		File selection = chooser.getSelectedFile();
		if (selection == null) {
			return;
		}

		try {
			List<TunnelerServer> servers = TunnelerServerTunnelFile.inst
					.load(selection);
			if (servers != null) {
				TunnelerServerContainer.inst.removeAllServers();
				for (TunnelerServer s : servers) {
					TunnelerServerContainer.inst.addServer(s);
				}
			}
		} catch (JDOMException ex) {
			Logger.getLogger(SSHTunnelerView.class.getName()).log(Level.SEVERE,
					null, ex);
		} catch (IOException ex) {
			Logger.getLogger(SSHTunnelerView.class.getName()).log(Level.SEVERE,
					null, ex);
		}
	}

	private void menu_item_save_srv_tunnelActionPerformed(
			java.awt.event.ActionEvent evt) {
		JFileChooser chooser = new JFileChooser();
		chooser.setMultiSelectionEnabled(false);
		chooser.setFileFilter(ServerTunnelFile.filter);

		chooser.showSaveDialog(null);

		File selection = chooser.getSelectedFile();
		if (selection == null) {
			return;
		}
		if (!selection.getName().endsWith(ServerTunnelFile.extension)) {
			selection = new File(selection.getPath()
					+ ServerTunnelFile.extension);
		}

		try {
			TunnelerServerTunnelFile.inst.save(selection,
					TunnelerServerContainer.inst.getServers());
		} catch (IOException ex) {
			Logger.getLogger(SSHTunnelerView.class.getName()).log(Level.SEVERE,
					null, ex);
		}
	}

	private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {
		SSHTunnelerApp.getApplication().quit();
	}

	private void mnu_show_configActionPerformed(java.awt.event.ActionEvent evt) {
		this.show_config();
	}

	private void mnu_toolsActionPerformed(java.awt.event.ActionEvent evt) {
		JFrame mainFrame = SSHTunnelerApp.getApplication().getMainFrame();
		ToolConfig gui = new ToolConfig(mainFrame);
		gui.setLocationRelativeTo(mainFrame);
		SSHTunnelerApp.getApplication().show(gui);
	}

	private void mnu_load_configActionPerformed(java.awt.event.ActionEvent evt) {
		JFileChooser chooser = new JFileChooser();
		chooser.setMultiSelectionEnabled(false);
		chooser.setFileFilter(Config.filter);

		chooser.showOpenDialog(null);

		File selection = chooser.getSelectedFile();
		if (selection == null) {
			return;
		}

		try {
			Config.inst.load(selection);
		} catch (JDOMException ex) {
			Logger.getLogger(SSHTunnelerView.class.getName()).log(Level.SEVERE,
					null, ex);
		} catch (IOException ex) {
			Logger.getLogger(SSHTunnelerView.class.getName()).log(Level.SEVERE,
					null, ex);
		}
	}

	private void mnu_save_configActionPerformed(java.awt.event.ActionEvent evt) {
		JFileChooser chooser = new JFileChooser();
		chooser.setMultiSelectionEnabled(false);
		chooser.setFileFilter(Config.filter);

		chooser.showSaveDialog(null);

		File selection = chooser.getSelectedFile();
		if (selection == null) {
			return;
		}
		if (!selection.getName().endsWith(Config.extension)) {
			selection = new File(selection.getPath() + Config.extension);
		}

		try {
			Config.inst.save(selection);
		} catch (IOException ex) {
			Logger.getLogger(SSHTunnelerView.class.getName()).log(Level.SEVERE,
					null, ex);
		}
	}

	private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {
		if (this.aboutBox == null) {
			JFrame mainFrame = SSHTunnelerApp.getApplication().getMainFrame();
			this.aboutBox = new SSHTunnelerAboutBox(mainFrame);
			this.aboutBox.setLocationRelativeTo(mainFrame);
		}
		SSHTunnelerApp.getApplication().show(this.aboutBox);
	}

	private javax.swing.JMenu jMenu1;
	private javax.swing.JScrollPane jScrollPane1;
	private javax.swing.JSeparator jSeparator1;
	private javax.swing.JSeparator jSeparator2;
	private javax.swing.JSeparator jSeparator3;
	private javax.swing.JTree jTree1;
	private javax.swing.JPanel mainPanel;
	private javax.swing.JMenuBar menuBar;
	private javax.swing.JMenuItem menu_item_load_srv_tunnel;
	private javax.swing.JMenuItem menu_item_save_srv_tunnel;
	private javax.swing.JMenuItem mnu_load_config;
	private javax.swing.JMenuItem mnu_save_config;
	private javax.swing.JMenuItem mnu_show_config;
	private javax.swing.JMenuItem mnu_tools;
	private JDialog aboutBox;

	public MyServerTunnelTreeNode getSelectedNode(MouseEvent e) {
		TreePath selPath = this.jTree1.getPathForLocation(e.getX(), e.getY());
		if (selPath == null) {
			return null;
		}
		this.jTree1.setSelectionPath(selPath);
		Object selection = this.jTree1.getLastSelectedPathComponent();

		if (selection == null) {
			return null;
		}
		if (!(selection instanceof MyServerTunnelTreeNode)) {
			return null;
		}

		return (MyServerTunnelTreeNode) selection;
	}

	public void refreshNode(MyServerTunnelTreeNode selectedNode) {
		selectedNode.refresh();
		((DefaultTreeModel) this.jTree1.getModel()).reload(selectedNode);
	}

	public void mousePressed(MouseEvent e) {
		if (e.isPopupTrigger()) {
			MyServerTunnelTreeNode selection = this.getSelectedNode(e);
			if (selection == null) {
				return;
			}
			JPopupMenu popup = selection.getPopup();
			popup.show((Component) e.getSource(), e.getX(), e.getY());
		}
	}

	public void mouseReleased(MouseEvent e) {
		if (e.isPopupTrigger()) {
			MyServerTunnelTreeNode selection = this.getSelectedNode(e);
			if (selection == null) {
				return;
			}
			JPopupMenu popup = selection.getPopup();
			popup.show((Component) e.getSource(), e.getX(), e.getY());
		}
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void show_config() {
		JFrame mainFrame = SSHTunnelerApp.getApplication().getMainFrame();
		SetConfig gui = new SetConfig(mainFrame);
		gui.setLocationRelativeTo(mainFrame);
		SSHTunnelerApp.getApplication().show(gui);
	}
}
